Calling a Code Converter Web Service from a Custom Task Pane in Word 2007

Summary: Create a Microsoft Visual Studio project that combines the utility of a Web service with the familiar user interface of Microsoft Office Word 2007. (22 printed pages)

Frank Rice, Microsoft Corporation

August 2008

Applies to: Microsoft Office Word 2007, Microsoft Visual Studio 2008, Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System, Second Edition

Contents

  • Overview

  • Building the Code Converter Add-in Project

  • Adding a Custom Ribbon to the Project

  • Creating the Custom Task Pane

  • Testing the Project

  • Conclusion

  • Additional Resources

Overview

In this article, you create a custom Microsoft Office Word 2007 Add-in in Microsoft Visual Studio 2008 (or Visual Studio 2005) with Visual Studio 2005 Tools for the 2007 Microsoft Office System, Second Edition (VSTO SE) that allows you to call a Web service to translate C# code into Visual Basic. The project features a number of technologies. First, you create a custom Microsoft Office Fluent Ribbon (hereafter known as the Ribbon) tab and button in a Word 2007 document. Clicking the button displays a custom task pane. The custom task pane contains a textbox to contain the C# code and another one to display the resulting Visual Basic. Next, you add a button to the task pane that connects to a simple Web service which does the code conversion and returns the results. Finally, you add another button to the task pane that inserts the Visual Basic code into the document.

Building the Code Converter Add-in Project

In the following steps, you create a Word 2007 Add-in in Microsoft Visual Studio.

To create the Add-in

  1. Start Microsoft Visual Studio 2008 (or Microsoft Visual Studio 2005).

  2. On the File menu, click New Project.

  3. (Visual Basic only) In the New Project dialog box, in the Project types pane, expand Visual Basic, Office, and then click 2007.

  4. (C# only) In the New Project dialog box, in the Project types pane, expand Other languages, Visual C#, Office, and then click 2007.

  5. In the Templates pane, select the Word 2007 Add-in icon.

  6. Specify the name of the project as Translator, and then click OK.

  7. Next, you need to add a reference to the ConvertCSharp2VBService Web service. Adding the reference is all you need to use the Execute method exposed by the service. On the Project menu, click Show All Files.

  8. In the Solution Explorer, right-click the Translator node and then click Add Web Reference.

    NoteNote

    If Add Web Reference is not one of the choices, click Add Service Reference. In the Add Service Reference dialog box, click the Advanced button and then click the Add Web Reference button.

  9. In the Add Web Reference dialog box, in the URL box, insert the following address: http://www.kamalpatel.net/ConvertCSharp2VBService.asmx.

  10. Click Go and then click Add Reference. The reference appears in the Solution Explorer under the Web References node.

  11. Although you have not built the custom task pane yet, you can still add code that displays or hides the task pane when the button on the Ribbon is clicked. In the Solution Explorer, right-click the ThisAddIn.vb (ThisAddIn.cs) node and click View Code.

  12. Copy and paste or type the following code into the code window just after the Public Class ThisAddIn (public partial class ThisAddIn{) statement.

    Private ctpConverter As Microsoft.Office.Tools.CustomTaskPane
    
    Public Sub AddTaskPane()
       ctpConverter = Me.CustomTaskPanes.Add(New converterControl(), _
          "Translate from C# to Visual Basic")
       ctpConverter.DockPosition = _
          Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight
            ctpConverter.Visible = True
    End Sub
    
    private Microsoft.Office.Tools.CustomTaskPane ctpConverter;
    
    public void AddTaskPane()
    {
    ctpConverter = this.CustomTaskPanes.Add(new converterControl(), " Translate from C# to Visual Basic");
       ctpConverter.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight;
       ctpConverter.Visible = true;
    }
    

    As its name implies, this procedure is used to display the task pane. First, you set a reference to a task pane object. In the AddTaskPane procedure, the converterControl custom task pane is added to the collection of task panes and assigned to the variable you defined earlier and the title of the task pane is set as Translate from C# to Visual Basic. The docked position of the pane is set and the task pane is displayed.

    Next, add the procedure that removes the task pane when the button is clicked again.

    Public Sub RemoveTaskPane ()
       If Me.CustomTaskPanes.Count > 0 Then
          Me.CustomTaskPanes.Remove(ctpConverter)
       End If
    End Sub
    
    public void RemoveTaskPane ()
    {
       if ((this.CustomTaskPanes.Count > 0))
       {
          this.CustomTaskPanes.Remove(ctpConverter);
       }
    }
    

    In this procedure, the count of open task panes is checked and if any task panes are displayed, the ctpConverter task pane is hidden, if it is open.

    Finally, add the following procedure, if it doesn't already exist. This procedure returns a reference to a new Ribbon1 object to Microsoft Office when initialized.

    Protected Overrides Function CreateRibbonExtensibilityObject() As _ Microsoft.Office.Core.IRibbonExtensibility
       Return New Ribbon1()
    End Function
    
    protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
    {
       return new Ribbon1();
    }
    

Adding a Custom Ribbon to the Project

In the following steps, you create the custom tab containing a button. This tab is added to the existing Ribbon in Word 2007 when the add-in is loaded.

To create the custom ribbon

  1. In the Solution Explorer, right-click the Translator node, point to Add, and then click Add New Item.

  2. In the Add New Item dialog box, in the Templates pane, select Ribbon (XML), and then click Add. The Ribbon1.vb (Ribbon1.cs) and Ribbon1.xml nodes are added to the Solution Explorer.

  3. Double-click the Ribbon1.xml file to display the code screen. The XML you see provides a starting point for customizing the Ribbon.

  4. To define the components of the Ribbon, replace the XML with the following code.

    <?xml version="1.0" encoding="UTF-8"?>
    <customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
      <ribbon>
        <tabs>
          <tab id="tabConverter" label="Convert Code"
               insertAfterMso="TabHome">
            <group id="grpConverter" label="Code Converter">
              <button id="btnDisplayPane" label="Show Translate Pane"
                      imageMso="MailMergeMatchFields"
                      size="large"
                      onAction="displayTaskPane"/>
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    

    In general, elements define controls on the Ribbon such as tabs, groups, buttons, or combo boxes, and attributes define properties of those controls such as a control's label or whether it is visible or hidden.

    Looking at the code, notice that in addition to the <tab> element, there is a <group> element and <button> element. A group is used as a container for controls with similar functions. For example, the Font group on the Home tab in Word 2007. The button is used to initialize some event such as displaying the task pane in this case.

    Also notice the insertAfterMso attribute of the <tab> element. Any attribute that ends in Mso specifies functionality that is built into Microsoft Office. In this case, the insertAfterMso attribute tells Word 2007 to insert the tab you create after the built-in Home tab.

    Next, the label attribute adds a caption to the button. The imageMso attribute assigns an image built into Microsoft Office to the button. In addition, the button has an onAction attribute that points to the procedure that is executed when you click the button. These procedures are also known as callback procedures. When the button is clicked, the onAction attribute calls back to Microsoft Office, which then executes the specified procedure.

    The net result of the XML is to create a tab on the Word 2007 Ribbon that looks like that seen in Figure 1.

    Figure 1. The code convertor Ribbon tab and controls

    Code convertor Ribbon tab

  5. Open the Ribbon.vb (Ribbon.cs) screen by right-clicking it in the Solution Explorer and then clicking View Code.

    NoteNote

    As you may notice, there are several lines of comments in the file that you may want to delete before continuing.

    When you add the Ribbon to your project, a Ribbon object class and a few procedures are already available in the Ribbon's code-behind file.

    Public Class Ribbon Implements Office.IRibbonExtensibility
    
     public class Ribbon : Office.IRibbonExtensibility
    

    The Ribbon class implements the Office.IRibbonExtensibility interface. This interface defines one method named GetCustomUI.

    Public Function GetCustomUI(ByVal ribbonID As String) As String Implements Office.IRibbonExtensibility.GetCustomUI
       Return GetResourceText("Translator.Ribbon.xml")
    End Function
    
    public string GetCustomUI(string ribbonID)
    {
       return GetResourceText("Translator.Ribbon.xml");
    }
    

    When the Ribbon is loaded by Microsoft Office, the GetCustomUI method is called and returns the XML that defines the Ribbon components to Microsoft Office.

    Next add the callback procedure to the class.

  6. In the Ribbon Callbacks block in the code screen, add the following procedure.

    Private converterControlExists As Boolean
    
    Public Sub displayTaskPane(ByVal control As Office.IRibbonControl)
       If Not converterControlExists Then
          Globals.ThisAddIn.AddTaskPane()
       Else
          Globals.ThisAddIn.RemoveTaskPane()
       End If
       converterControlExists = Not converterControlExists
    End Sub
    
    bool converterControlExists = false;
    
    public void displayTaskPane(Office.IRibbonControl control)
    {
       if (!converterControlExists)
       {
          Globals.ThisAddIn.AddTaskPane();
       }
       else
       {
          Globals.ThisAddIn.RemoveTaskPane();
       }
       converterControlExists = ! converterControlExists;
    }
    

    This procedure is called when the Display Task Pane button is clicked. As stated earlier, its purpose is to display or hide the custom task pane. It does this by checking state of the converterControlExistsBoolean variable. Initially, this variable is set to False. When the procedure is called, Not converterControlExists (!converterControlExists) equates to True so the AddTaskPane method of the ThisAddIn class is called. This causes the task pane to be displayed. The converterControlExists variable is then set to True. When the button is clicked again, Not converterControlExists (!converterControlExists) now equals False, the RemoveTaskPane procedure is called, and the task pane is hidden.

Creating the Custom Task Pane

In the following steps, you create the code converter task pane and populate it with controls.

To create the custom task pane

  1. In the Solution Explorer, right-click the Translator node, point to Add, and then click Add New Item.

  2. In the Add New Item dialog box, select the User Control, name it converterControl.vb (converterControl.cs) and click Add.

    Next, add the task pane controls.

  3. On the View menu, click Toolbox.

    From the toolbox, add the controls specified in Table 1 to the converterControl[Designer] screen and set the properties as shown. The design should look similar to Figure 2.

Table 1. Add these controls to the converterControl control

Control Type

Property

Setting

Label

Text

Type C# here:

TextBox

Name

txtCS

Multiline

True

Size

160, 164

Label

Text

Visual Basic:

TextBox

Name

txtVB

Multiline

True

Size

160, 164

Button

Name

btnTranslate

Text

Translate

Button

Name

btnInsert

Text

Insert Code

Figure 2. The converterControl control

converterControl control

Now add code for the Translate button.

  1. In the Solution Explorer, right-click the converterControl.vb (converterControl.cs) node, and click View Code.

  2. At the top of the screen, add the following namespace declaration.

    Imports Word = Microsoft.Office.Interop.Word
    
    using Word = Microsoft.Office.Interop.Word;
    
  3. In the convertControl[Designer] screen, double-click the Translate button. Replace the empty btnTranslate_Click procedure with the following code.

    Private Sub btnTranslate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTranslate.Click
       Dim strCS As String = txtCS.Text
       Dim strVB As String
    
       Dim cnvt As net.kamalpatel.www.ConvertCSharp2VBService
       cnvt = New net.kamalpatel.www.ConvertCSharp2VBService
       strVB = cnvt.Execute(strCS)
       txtVB.Text = Replace(strVB, vbLf, vbCrLf)
    End Sub
    
    private void btnTranslate_Click(object sender, EventArgs e)
    {
       string strCS = txtCS.Text;
       string strVB;
    
       net.kamalpatel.www.ConvertCSharp2VBService cnvt;
       cnvt = new net.kamalpatel.www.ConvertCSharp2VBService();
       strVB = cnvt.Execute(strCS);
       txtVB.Text = strVB.Replace("\n", "\r\n");
    }
    

    The btnTranslate_Click procedure is called when you click the Translate button on the task pane. First, it assigns the value representing the C# code from the txtCS textbox to a variable. The cnvt variable is initialized to point to the Web service and a new instance of the reference is created. This allows you to call the Web service's Execute method. The returned code Visual Basic is then formatted for display in the txtVB textbox on the task pane.

  4. In the converterControl[Designer] screen, double-click the Insert Code button and replace the empty btnInsert_Click procedure with the following code.

    Private Sub btnInsert_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInsert.Click
       Dim rng As Word.Range = Globals.ThisAddIn.Application.ActiveDocument.Content
       Dim strVB As String = txtVB.Text
       Dim intIndex As Integer
    
       ' Remove the attribution statements before inserting
       ' the code into the document.
       ' Get index of end of code block.
       intIndex = strVB.LastIndexOf("' Converted")
    
       ' Get just the code block.
       strVB = strVB.Substring(0, intIndex)
    
       ' Insert the code block into the document.
       rng.InsertBefore(strVB)
    End Sub
    
    private void btnInsert_Click(object sender, EventArgs e)
    {
       Word.Range rng  = Globals.ThisAddIn.Application.ActiveDocument.Content;
       string strVB = txtVB.Text;
       int intIndex;
    
       // Remove the attribution statements before inserting
       // the code into the document.
       // Get index of end of code block.
       intIndex = strVB.LastIndexOf("' Converted");
    
       // Get just the code block.
       strVB = strVB.Substring(0, intIndex);
    
       // Insert the code block into the document.
       rng.InsertBefore(strVB);
    
    }
    

    In this procedure, a reference to the Range variable is set. The converted Visual Basic code is inserted into this range in the document. The code conversion Web service appends the Web service's author's name to the Visual Basic output. You likely do not want this attribution included when the code is inserted into the document. The procedure removes this by looking for the occurrence of a key word and removing the substring containing just the Visual Basic code. Finally, the code is inserted into the document.

Testing the Project

In the following steps, you build and test the Add-in project.

To test the add-in project

  1. On the Debug menu, click Start Debugging. The project is built and Word 2007 is displayed.

  2. On the right-side of the Home tab, click the Convert Code tab and then click the Display Translate Pane button. The converter task pane is displayed on the right side of the screen.

  3. In the top textbox, type or paste the C# code.

  4. Next, click the Translate button.

  5. In the Visual Basic textbox, the Visual Basic code is displayed as shown in Figure 3.

    Figure 3. After clicking the Translate button, C# is converted to Visual Basic

    Visual Basic code

  6. Click the Insert Code button to insert the converted text into the document.

  7. Close the document once the search is complete.

Conclusion

In this project, you had an opportunity to see a number of technologies work together to form a simple but useful tool. The combination of Microsoft Visual Studio, Microsoft Office 2007, and Web services gives you to the foundation for creating a virtually unlimited number of powerful and useful applications. I encourage you to extend this knowledge by creating your own Web service and then packaging this with a project similar to the one you created in this article, as a complete solution.

Additional Resources

You can find addition information on the technologies discussed in this article at the following locations.